// $Id: php_qqwry.c 4 2008-08-10 06:45:44Z glinus $

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_qqwry.h"

static char ini_data_path[] = "qqwry.data_path";

int le_qqwry_library;
int le_qqwry_library_persist;

ZEND_DECLARE_MODULE_GLOBALS(qqwry)

static function_entry qqwry_functions[] = {
    PHP_FE(qqwry_query, NULL)
    PHP_FE(qqwry_open,  NULL)
    PHP_FE(qqwry_popen, NULL)
    PHP_FE(qqwry_close, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry qqwry_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_QQWRY_EXTNAME,
    qqwry_functions,
    PHP_MINIT(qqwry),
    PHP_MSHUTDOWN(qqwry),
    PHP_RINIT(qqwry),
    NULL,
    PHP_MINFO(qqwry),
#if ZEND_MODULE_API_NO >= 20010901
    PHP_QQWRY_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_QQWRY
ZEND_GET_MODULE(qqwry)
#endif

PHP_INI_BEGIN()
    PHP_INI_ENTRY("qqwry.data_path", "/usr/share/qqwry.dat", PHP_INI_ALL, NULL)
PHP_INI_END()

static void php_qqwry_init_globals(zend_qqwry_globals *qqwry_globals)
{
}

PHP_RINIT_FUNCTION(qqwry)
{
    QQWRY_G(counter) = 0;
    return SUCCESS;
}

static void php_qqwry_library_persist_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
    php_qqwry_library *qqwry= (php_qqwry_library *)rsrc->ptr;
    if (qqwry) {
        if (qqwry->fp) {
            fclose(qqwry->fp);
        }
        if (qqwry->data_path) {
            pefree(qqwry->data_path, 1);
        }
        pefree(qqwry, 1);
    }
}

static void php_qqwry_library_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
    php_qqwry_library *qqwry= (php_qqwry_library *)rsrc->ptr;
    if (qqwry->fp) {
        fclose(qqwry->fp);
    }
    if (qqwry->data_path) {
        efree(qqwry->data_path);
    }
    efree(qqwry);
}

PHP_MINIT_FUNCTION(qqwry)
{
    le_qqwry_library = zend_register_list_destructors_ex(
            php_qqwry_library_dtor, NULL, PHP_QQWRY_LIBRARY_RES_NAME, module_number);
    le_qqwry_library_persist = zend_register_list_destructors_ex(
            NULL, php_qqwry_library_persist_dtor, PHP_QQWRY_LIBRARY_RES_NAME, module_number);

    ZEND_INIT_MODULE_GLOBALS(qqwry, php_qqwry_init_globals, NULL);

    REGISTER_INI_ENTRIES();

    return SUCCESS;
}

PHP_MSHUTDOWN_FUNCTION(qqwry)
{
    UNREGISTER_INI_ENTRIES();

    return SUCCESS;
}

/**
 * Do Query
 * @param string word
 * @return array matches
 */
PHP_FUNCTION(qqwry_query)
{
    php_qqwry_library *qqwry;
    FILE *fp;
    zval *zlibrary;
    char *word;
    int name_len;
    char *country;
    char *area;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zlibrary, &word, &name_len) == FAILURE) {
        RETURN_FALSE;
    }

    ++QQWRY_G(counter);
    ZEND_FETCH_RESOURCE2(qqwry, php_qqwry_library*, &zlibrary, -1, PHP_QQWRY_LIBRARY_RES_NAME, le_qqwry_library, le_qqwry_library_persist);

    fp = qqwry->fp;
    array_init(return_value);

    country = malloc(sizeof(char) * 64);
    area = malloc(sizeof(char) * 64);
    memset(country, 0, sizeof(char) * 64);
    memset(area, 0, sizeof(char) * 64);

    if (qqwrt_get_location(country, area, word, fp)) {
        add_assoc_string(return_value, "country", country, 1);
        add_assoc_string(return_value, "area", area, 1);
    }

    free(country);
    free(area);
}

/* Resource Init */
PHP_FUNCTION(qqwry_open)
{
    php_qqwry_library *qqwry;
    char *directory;
    int name_len;

    if (0 == ZEND_NUM_ARGS()) {
        directory = INI_STR(ini_data_path);
    }
    else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &directory, &name_len) == FAILURE) {
        RETURN_FALSE;
    }

    qqwry = (php_qqwry_library *)emalloc(sizeof(php_qqwry_library));
    qqwry->fp  = fopen(directory, "r");
    qqwry->data_path = (char *)emalloc(name_len + 1);
    memcpy(qqwry->data_path, directory, name_len + 1);

    if (NULL == qqwry)
        RETURN_FALSE;

    ZEND_REGISTER_RESOURCE(return_value, qqwry, le_qqwry_library);
}

/* Resource Persist Init */
PHP_FUNCTION(qqwry_popen)
{
    php_qqwry_library *qqwry;
    char *directory;
    char *key;
    int key_len, name_len;
    list_entry *le, new_le;

    if (0 == ZEND_NUM_ARGS()) {
        directory = INI_STR(ini_data_path);
    }
    else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &directory, &name_len) == FAILURE) {
        RETURN_FALSE;
    }

    /* Look for an established resource */
    key_len = spprintf(&key, 0, "qqwry_library__%s", directory);
    if (zend_hash_find(&EG(persistent_list), key, key_len + 1,(void **)&le) == SUCCESS) {
        /* An entry for this library already exists */
        ZEND_REGISTER_RESOURCE(return_value, le->ptr, le_qqwry_library_persist);
        efree(key);
        return;
    }

    /* New library, allocate a structure */
    qqwry = (php_qqwry_library *)pemalloc(sizeof(php_qqwry_library), 1);
    ZEND_REGISTER_RESOURCE(return_value, qqwry, le_qqwry_library_persist);
    qqwry->fp = fopen(directory, "r");
    qqwry->data_path = (char *)pemalloc(name_len + 1, 1);
    memcpy(qqwry->data_path, directory, name_len + 1);

    if (NULL == qqwry)
        RETURN_FALSE;

    /* Store a reference in the persistence list */
    new_le.ptr = qqwry;
    new_le.type = le_qqwry_library_persist;
    zend_hash_add(&EG(persistent_list), key, key_len + 1, &new_le, sizeof(list_entry), NULL);

    efree(key);
}

/* Resource Delete */
PHP_FUNCTION(qqwry_close)
{
    zval *zlibrary;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zlibrary) == FAILURE) {
        RETURN_FALSE;
    }

    zend_list_delete(Z_LVAL_P(zlibrary));
    RETURN_TRUE;
}

/* phpinfo */
PHP_MINFO_FUNCTION(qqwry)
{
    php_info_print_table_start();
    php_info_print_table_row(2, "QQWry Support", "enabled" );
    php_info_print_table_row(2, "Dictionary Repos", INI_STR(ini_data_path) );
    php_info_print_table_row(2, "Global Counter",   QQWRY_G(counter) );
    php_info_print_table_end();

}
